home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 002 / emacssrc.arc / EXEC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1987-02-10  |  17.0 KB  |  901 lines

  1. /*    This file is for functions dealing with execution of
  2.     commands, command lines, buffers, files and startup files
  3.  
  4.     written 1986 by Daniel Lawrence                */
  5.  
  6. #include    <stdio.h>
  7. #include    "estruct.h"
  8. #include    "edef.h"
  9.  
  10. #if    MEGAMAX & ST520
  11. overlay    "exec"
  12. #endif
  13.  
  14. #if    DEBUGM
  15. char outline[NSTRING];        /* global string to hold debug line text */
  16. #endif
  17.  
  18. /* namedcmd:    execute a named command even if it is not bound */
  19.  
  20. namedcmd(f, n)
  21.  
  22. int f, n;    /* command arguments [passed through to command executed] */
  23.  
  24. {
  25.     register (*kfunc)();    /* ptr to the requexted function to bind to */
  26.     int (*getname())();
  27.  
  28.     /* prompt the user to type a named command */
  29.     mlwrite(": ");
  30.  
  31.     /* and now get the function name to execute */
  32.     kfunc = getname();
  33.     if (kfunc == NULL) {
  34.         mlwrite("[No such function]");
  35.         return(FALSE);
  36.     }
  37.  
  38.     /* and then execute the command */
  39.     return((*kfunc)(f, n));
  40. }
  41.  
  42. /*    execcmd:    Execute a command line command to be typed in
  43.             by the user                    */
  44.  
  45. execcmd(f, n)
  46.  
  47. int f, n;    /* default Flag and Numeric argument */
  48.  
  49. {
  50.     register int status;        /* status return */
  51.     char cmdstr[NSTRING];        /* string holding command to execute */
  52.  
  53.     /* get the line wanted */
  54.     if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE)
  55.         return(status);
  56.  
  57.     execlevel = 0;
  58.     return(docmd(cmdstr));
  59. }
  60.  
  61. /*    docmd:    take a passed string as a command line and translate
  62.         it to be executed as a command. This function will be
  63.         used by execute-command-line and by all source and
  64.         startup files. Lastflag/thisflag is also updated.
  65.  
  66.     format of the command line is:
  67.  
  68.         {# arg} <command-name> {<argument string(s)>}
  69.  
  70.     Directives start with a "!" and include:
  71.  
  72.     !endm        End a macro
  73.     !if (cond)    conditional execution
  74.     !else
  75.     !endif
  76.     !return        Return (terminating current macro)
  77.     !goto <label>    Jump to a label in the current macro
  78.  
  79.     Line Labels begin with a "*" in column 1, like:
  80.  
  81.     *LBL01
  82. */
  83.  
  84. docmd(cline)
  85.  
  86. char *cline;    /* command line to execute */
  87.  
  88. {
  89.     register int f;        /* default argument flag */
  90.     register int n;        /* numeric repeat value */
  91.     register int i;
  92.     int (*fnc)();        /* function to execute */
  93.     int status;        /* return status of function */
  94.     int oldcle;        /* old contents of clexec flag */
  95.     int llen;        /* length of cline */
  96.     int force;        /* force TRUE result? */
  97.     char *tmp;        /* tmp pointer into cline */
  98.     struct LINE *lp;    /* a line pointer */
  99.     char *oldestr;        /* original exec string */
  100.     char token[NSTRING];    /* next token off of command line */
  101.     int (*fncmatch())();
  102. #if    DEBUGM
  103.     /* if $debug == TRUE, every line to execute
  104.        gets echoed and a key needs to be pressed to continue
  105.        ^G will abort the command */
  106.     register char *sp;    /* pointer into buf to expand %s */
  107.  
  108.     if (macbug) {
  109.         strcpy(outline, "<<<");
  110. #if    1    /* debug if levels */
  111.         strcat(outline, itoa(execlevel));
  112.         strcat(outline, ":");
  113. #endif
  114.         strcat(outline, cline);
  115.         strcat(outline, ">>>");
  116.  
  117.         /* change all '%' to ':' so mlwrite won't expect arguments */
  118.         sp = outline;
  119.         while (*sp) {
  120.             if (*sp++ == '%')
  121.                 *(sp-1) = ':';
  122.         }
  123.  
  124.         /* write out the debug line */
  125.         mlwrite(outline);
  126.         update(TRUE);
  127.  
  128.         /* and get the keystroke */
  129.         if (tgetc() == 7) {
  130.             mlwrite("[Macro aborted]");
  131.             return(FALSE);
  132.         }
  133.     }
  134. #endif
  135.         
  136.     /* dump comments here */
  137.     if (*cline == ';')
  138.         return(TRUE);
  139.  
  140.     /* eat leading spaces */
  141.     while (*cline == ' ' || *cline == '\t')
  142.         ++cline;
  143.  
  144.     /* check to see if this line turns macro storage off */
  145.     if (cline[0] == '!' && strncmp(&cline[1], "endm", 4) == 0) {
  146.         mstore = FALSE;
  147.         bstore = NULL;
  148.         return(TRUE);
  149.     }
  150.  
  151.     /* if macro store is on, just salt this away */
  152.     if (mstore) {
  153.         /* allocate the space for the line */
  154.         llen = strlen(cline);
  155.         if ((lp=lalloc(llen)) == NULL) {
  156.             mlwrite("Out of memory while storing macro");
  157.             return (FALSE);
  158.         }
  159.  
  160.         /* copy the text into the new line */
  161.         for (i=0; i<llen; ++i)
  162.             lputc(lp, i, cline[i]);
  163.  
  164.         /* attach the line to the end of the buffer */
  165.                bstore->b_linep->l_bp->l_fp = lp;
  166.         lp->l_bp = bstore->b_linep->l_bp;
  167.         bstore->b_linep->l_bp = lp;
  168.         lp->l_fp = bstore->b_linep;
  169.         return (TRUE);
  170.     }
  171.     
  172.     /* dump labels here */
  173.     if (*cline == '*')
  174.         return(TRUE);
  175.  
  176.     force = FALSE;
  177.     oldestr = execstr;    /* save last ptr to string to execute */
  178.     execstr = cline;    /* and set this one as current */
  179.  
  180.     /* process directives */
  181.     if (*cline == '!') {
  182.         /* save directive location and skip it */
  183.         tmp = cline;
  184.         while (*execstr && *execstr != ' ' && *execstr != '\t')
  185.             ++execstr;
  186.  
  187.         if (tmp[1] == 'f' && tmp[2] == 'o') {
  188.             force = TRUE;
  189.             goto do001;
  190.  
  191.         } else if (tmp[1] == 'i' && tmp[2] == 'f') {
  192.  
  193.             /* IF directive */
  194.             /* grab the value of the logical exp */
  195.             if (execlevel == 0) {
  196.                 if ((status = macarg(token)) != TRUE) {
  197.                     execstr = oldestr;
  198.                     return(status);
  199.                 }
  200.                 status = stol(token);
  201.             } else
  202.                 status = TRUE;
  203.  
  204.             if (status) {
  205.  
  206.                 /* IF (TRUE) */
  207.                 if (execlevel != 0)
  208.                     ++execlevel;
  209.             } else {
  210.  
  211.                 /* IF (FALSE) */
  212.                 ++execlevel;
  213.             }
  214.  
  215.         } else if (tmp[1] == 'e' && tmp[2] == 'l') {
  216.  
  217.             /* ELSE directive */
  218.             if (execlevel == 1)
  219.                 --execlevel;
  220.             else if (execlevel == 0 )
  221.                 ++execlevel;
  222.  
  223.         } else if (tmp[1] == 'e' && tmp[2] == 'n') {
  224.  
  225.             /* ENDIF directive */
  226.             if (execlevel)
  227.                 --execlevel;
  228.  
  229.         } else if (tmp[1] == 'r' && tmp[2] == 'e') {
  230.  
  231.             /* RETURN directive */
  232.             execstr = oldestr;
  233.             if (execlevel)
  234.                 return(TRUE);
  235.             else
  236.                 return(RET);
  237.  
  238.         } else if (tmp[1] == 'g' && tmp[2] == 'o') {
  239.  
  240.             /* GOTO directive */
  241.             /* .....only if we are currently executing */
  242.             if (execlevel) {
  243.                 execstr = oldestr;
  244.                 return(TRUE);
  245.             }
  246.  
  247.             while (*execstr == ' ' || *execstr == '\t')
  248.                 ++execstr;
  249.             strncpy(golabel, execstr, NPAT - 1);
  250.             return(GOLINE);
  251.  
  252.         } else {
  253.             mlwrite("%%Unknown Directive");
  254.             return(FALSE);
  255.         }
  256.  
  257.         /* restore execstr and exit */
  258.         execstr = oldestr;
  259.         return(TRUE);
  260.     }
  261.  
  262. do001:    /* if we are scanning and not executing..go back here */
  263.     if (execlevel) {
  264.         execstr = oldestr;
  265.         return(TRUE);
  266.     }
  267.  
  268.     /* first set up the default command values */
  269.     f = FALSE;
  270.     n = 1;
  271.     lastflag = thisflag;
  272.     thisflag = 0;
  273.  
  274.     if ((status = macarg(token)) != TRUE) {    /* and grab the first token */
  275.         execstr = oldestr;
  276.         return(status);
  277.     }
  278.  
  279.     /* process leadin argument */
  280.     if (gettyp(token) != TKCMD) {
  281.         f = TRUE;
  282.         n = atoi(getval(token));
  283.  
  284.         /* and now get the command to execute */
  285.         if ((status = macarg(token)) != TRUE) {
  286.             execstr = oldestr;
  287.             return(status);    
  288.         }    
  289.     }
  290.  
  291.     /* and match the token to see if it exists */
  292.     if ((fnc = fncmatch(token)) == NULL) {
  293.         mlwrite("[No such Function]");
  294.         execstr = oldestr;
  295.         return(FALSE);
  296.     }
  297.     
  298.     /* save the arguments and go execute the command */
  299.     oldcle = clexec;        /* save old clexec flag */
  300.     clexec = TRUE;            /* in cline execution */
  301.     status = (*fnc)(f, n);        /* call the function */
  302.     cmdstatus = status;        /* save the status */
  303.     if (force)            /* force the status */
  304.         status = TRUE;
  305.     clexec = oldcle;        /* restore clexec flag */
  306.     execstr = oldestr;
  307.     return(status);
  308. }
  309.  
  310. /* token:    chop a token off a string
  311.         return a pointer past the token
  312. */
  313.  
  314. char *token(src, tok)
  315.  
  316. char *src, *tok;    /* source string, destination token string */
  317.  
  318. {
  319.     register int quotef;    /* is the current string quoted? */
  320.  
  321.     /* first scan past any whitespace in the source string */
  322.     while (*src == ' ' || *src == '\t')
  323.         ++src;
  324.  
  325.     /* scan through the source string */
  326.     quotef = FALSE;
  327.     while (*src) {
  328.         /* process special characters */
  329.         if (*src == '~') {
  330.             ++src;
  331.             if (*src == 0)
  332.                 break;
  333.             switch (*src++) {
  334.                 case 'r':    *tok++ = 13; break;
  335.                 case 'n':    *tok++ = 10; break;
  336.                 case 't':    *tok++ = 9;  break;
  337.                 case 'b':    *tok++ = 8;  break;
  338.                 case 'f':    *tok++ = 12; break;
  339.                 default:    *tok++ = *(src-1);
  340.             }
  341.         } else {
  342.             /* check for the end of the token */
  343.             if (quotef) {
  344.                 if (*src == '"')
  345.                     break;
  346.             } else {
  347.                 if (*src == ' ' || *src == '\t')
  348.                     break;
  349.             }
  350.  
  351.             /* set quote mode if qoute found */
  352.             if (*src == '"')
  353.                 quotef = TRUE;
  354.  
  355.  
  356.             /* record the character */
  357.             *tok++ = *src++;
  358.         }
  359.     }
  360.  
  361.     /* terminate the token and exit */
  362.     if (*src)
  363.         ++src;
  364.     *tok = 0;
  365.     return(src);
  366. }
  367.  
  368. macarg(tok)    /* get a macro line argument */
  369.  
  370. char *tok;    /* buffer to place argument */
  371.  
  372. {
  373.     int savcle;    /* buffer to store original clexec */
  374.     int status;
  375.  
  376.     savcle = clexec;    /* save execution mode */
  377.     clexec = TRUE;        /* get the argument */
  378.     status = nextarg("", tok, NSTRING, ctoec('\n'));
  379.     clexec = savcle;    /* restore execution mode */
  380.     return(status);
  381. }
  382.  
  383. /*    nextarg:    get the next argument    */
  384.  
  385. nextarg(prompt, buffer, size, terminator)
  386.  
  387. char *prompt;        /* prompt to use if we must be interactive */
  388. char *buffer;        /* buffer to put token into */
  389. char *size;        /* size of the buffer */
  390. int terminator;        /* terminating char to be used on interactive fetch */
  391.  
  392. {
  393.     /* if we are interactive, go get it! */
  394.     if (clexec == FALSE)
  395.         return(getstring(prompt, buffer, size, terminator));
  396.  
  397.     /* grab token and advance past */
  398.     execstr = token(execstr, buffer);
  399.  
  400.     /* evaluate it */
  401.     strcpy(buffer, getval(buffer));
  402.     return(TRUE);
  403. }
  404.  
  405. /*    storemac:    Set up a macro buffer and flag to store all
  406.             executed command lines there            */
  407.  
  408. storemac(f, n)
  409.  
  410. int f;        /* default flag */
  411. int n;        /* macro number to use */
  412.  
  413. {
  414.     register struct BUFFER *bp;    /* pointer to macro buffer */
  415.     char bname[NBUFN];        /* name of buffer to use */
  416.  
  417.     /* must have a numeric argument to this function */
  418.     if (f == FALSE) {
  419.         mlwrite("No macro specified");
  420.         return(FALSE);
  421.     }
  422.  
  423.  
  424.     /* range check the macro number */
  425.     if (n < 1 || n > 40) {
  426.         mlwrite("Macro number out of range");
  427.         return(FALSE);
  428.     }
  429.  
  430.     /* construct the macro buffer name */
  431.     strcpy(bname, "[Macro xx]");
  432.     bname[7] = '0' + (n / 10);
  433.     bname[8] = '0' + (n % 10);
  434.  
  435.     /* set up the new macro buffer */
  436.     if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) {
  437.         mlwrite("Can not create macro");
  438.         return(FALSE);
  439.     }
  440.  
  441.     /* and make sure it is empty */
  442.     bclear(bp);
  443.  
  444.     /* and set the macro store pointers to it */
  445.     mstore = TRUE;
  446.     bstore = bp;
  447.     return(TRUE);
  448. }
  449.  
  450. /*    execbuf:    Execute the contents of a buffer of commands    */
  451.  
  452. execbuf(f, n)
  453.  
  454. int f, n;    /* default flag and numeric arg */
  455.  
  456. {
  457.         register BUFFER *bp;        /* ptr to buffer to execute */
  458.         register int status;        /* status return */
  459.         char bufn[NBUFN];        /* name of buffer to execute */
  460.  
  461.     /* find out what buffer the user wants to execute */
  462.         if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE)
  463.                 return(status);
  464.  
  465.     /* find the pointer to that buffer */
  466.         if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
  467.         mlwrite("No such buffer");
  468.                 return(FALSE);
  469.         }
  470.  
  471.     /* and now execute it as asked */
  472.     while (n-- > 0)
  473.         if ((status = dobuf(bp)) != TRUE)
  474.             return(status);
  475.     return(TRUE);
  476. }
  477.  
  478. /*    dobuf:    execute the contents of the buffer pointed to
  479.         by the passed BP                */
  480.  
  481. dobuf(bp)
  482.  
  483. BUFFER *bp;    /* buffer to execute */
  484.  
  485. {
  486.         register int status;        /* status return */
  487.     register LINE *lp;        /* pointer to line to execute */
  488.     register LINE *hlp;        /* pointer to line header */
  489.     register LINE *glp;        /* line to goto */
  490.     register int linlen;        /* length of line to execute */
  491.     register WINDOW *wp;        /* ptr to windows to scan */
  492.     char *eline;            /* text of line to execute */
  493.  
  494.     /* clear IF level flags */
  495.     execlevel = 0;
  496.  
  497.     /* starting at the beginning of the buffer */
  498.     hlp = bp->b_linep;
  499.     lp = hlp->l_fp;
  500.     while (lp != hlp) {
  501.         /* allocate eline and copy macro line to it */
  502.         linlen = lp->l_used;
  503.         if ((eline = malloc(linlen+1)) == NULL) {
  504.             mlwrite("%%Out of Memory during macro execution");
  505.             return(FALSE);
  506.         }
  507.         strncpy(eline, lp->l_text, linlen);
  508.         eline[linlen] = 0;    /* make sure it ends */
  509.  
  510.         /* trim leading whitespace */
  511.         while (eline[0] == ' ' || eline[0] == '\t')
  512.             strcpy(eline, &eline[1]);
  513.  
  514.         /* if it is not a comment, execute it */
  515.         if (eline[0] != 0 && eline[0] != ';') {
  516.             status = docmd(eline);
  517.  
  518.             /* if it is a !GOTO directive, deal with it */
  519.             if (status == GOLINE) {
  520.                 linlen = strlen(golabel);
  521.                 glp = hlp->l_fp;
  522.                 while (glp != hlp) {
  523.                     if (*glp->l_text == '*' &&
  524.                         (strncmp(&glp->l_text[1], golabel,
  525.                                 linlen) == 0)) {
  526.                         lp = glp;
  527.                         status = TRUE;
  528.                     }
  529.                 glp = glp->l_fp;
  530.                 }
  531.             }
  532.  
  533.             if (status == GOLINE) {
  534.                 mlwrite("%%No such label");
  535.                 return(FALSE);
  536.             }
  537.  
  538.             /* if it is a !RETURN directive...do so */
  539.             if (status == RET) {
  540.                 free(eline);
  541.                 break;
  542.             }
  543.  
  544.             /* check for a command error */
  545.             if (status != TRUE) {
  546.                 /* look if buffer is showing */
  547.                 wp = wheadp;
  548.                 while (wp != NULL) {
  549.                     if (wp->w_bufp == bp) {
  550.                         /* and point it */
  551.                         wp->w_dotp = lp;
  552.                         wp->w_doto = 0;
  553.                         wp->w_flag |= WFHARD;
  554.                     }
  555.                     wp = wp->w_wndp;
  556.                 }
  557.                 /* in any case set the buffer . */
  558.                 bp->b_dotp = lp;
  559.                 bp->b_doto = 0;
  560.                 free(eline);
  561.                 execlevel = 0;
  562.                 return(status);
  563.             }
  564.         }
  565.  
  566.         /* on to the next line */
  567.         free(eline);
  568.         lp = lp->l_fp;
  569.     }
  570.  
  571.     /* exit the current function */
  572.     execlevel = 0;
  573.         return(TRUE);
  574. }
  575.  
  576. execfile(f, n)    /* execute a series of commands in a file
  577. */
  578.  
  579. int f, n;    /* default flag and numeric arg to pass on to file */
  580.  
  581. {
  582.     register int status;    /* return status of name query */
  583.     char *fname[NSTRING];    /* name of file to execute */
  584.  
  585.     if ((status = mlreply("File to execute: ", fname, NSTRING -1)) != TRUE)
  586.         return(status);
  587.  
  588.     /* otherwise, execute it */
  589.     while (n-- > 0)
  590.         if ((status=dofile(fname)) != TRUE)
  591.             return(status);
  592.  
  593.     return(TRUE);
  594. }
  595.  
  596. /*    dofile:    yank a file into a buffer and execute it
  597.         if there are no errors, delete the buffer on exit */
  598.  
  599. dofile(fname)
  600.  
  601. char *fname;    /* file name to execute */
  602.  
  603. {
  604.     register BUFFER *bp;    /* buffer to place file to exeute */
  605.     register BUFFER *cb;    /* temp to hold current buf while we read */
  606.     register int status;    /* results of various calls */
  607.     char bname[NBUFN];    /* name of buffer */
  608.  
  609.     makename(bname, fname);        /* derive the name of the buffer */
  610.     if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */
  611.         return(FALSE);
  612.  
  613.     bp->b_mode = MDVIEW;    /* mark the buffer as read only */
  614.     cb = curbp;        /* save the old buffer */
  615.     curbp = bp;        /* make this one current */
  616.     /* and try to read in the file to execute */
  617.     if ((status = readin(fname, FALSE)) != TRUE) {
  618.         curbp = cb;    /* restore the current buffer */
  619.         return(status);
  620.     }
  621.  
  622.     /* go execute it! */
  623.     curbp = cb;        /* restore the current buffer */
  624.     if ((status = dobuf(bp)) != TRUE)
  625.         return(status);
  626.  
  627.     /* if not displayed, remove the now unneeded buffer and exit */
  628.     if (bp->b_nwnd == 0)
  629.         zotbuf(bp);
  630.     return(TRUE);
  631. }
  632.  
  633. /*    cbuf:    Execute the contents of a numbered buffer    */
  634.  
  635. cbuf(f, n, bufnum)
  636.  
  637. int f, n;    /* default flag and numeric arg */
  638. int bufnum;    /* number of buffer to execute */
  639.  
  640. {
  641.         register BUFFER *bp;        /* ptr to buffer to execute */
  642.         register int status;        /* status return */
  643.     static char bufname[] = "[Macro xx]";
  644.  
  645.     /* make the buffer name */
  646.     bufname[7] = '0' + (bufnum / 10);
  647.     bufname[8] = '0' + (bufnum % 10);
  648.  
  649.     /* find the pointer to that buffer */
  650.         if ((bp=bfind(bufname, FALSE, 0)) == NULL) {
  651.             mlwrite("Macro not defined");
  652.                 return(FALSE);
  653.         }
  654.  
  655.     /* and now execute it as asked */
  656.     while (n-- > 0)
  657.         if ((status = dobuf(bp)) != TRUE)
  658.             return(status);
  659.     return(TRUE);
  660. }
  661.  
  662. cbuf1(f, n)
  663.  
  664. {
  665.     cbuf(f, n, 1);
  666. }
  667.  
  668. cbuf2(f, n)
  669.  
  670. {
  671.     cbuf(f, n, 2);
  672. }
  673.  
  674. cbuf3(f, n)
  675.  
  676. {
  677.     cbuf(f, n, 3);
  678. }
  679.  
  680. cbuf4(f, n)
  681.  
  682. {
  683.     cbuf(f, n, 4);
  684. }
  685.  
  686. cbuf5(f, n)
  687.  
  688. {
  689.     cbuf(f, n, 5);
  690. }
  691.  
  692. cbuf6(f, n)
  693.  
  694. {
  695.     cbuf(f, n, 6);
  696. }
  697.  
  698. cbuf7(f, n)
  699.  
  700. {
  701.     cbuf(f, n, 7);
  702. }
  703.  
  704. cbuf8(f, n)
  705.  
  706. {
  707.     cbuf(f, n, 8);
  708. }
  709.  
  710. cbuf9(f, n)
  711.  
  712. {
  713.     cbuf(f, n, 9);
  714. }
  715.  
  716. cbuf10(f, n)
  717.  
  718. {
  719.     cbuf(f, n, 10);
  720. }
  721.  
  722. cbuf11(f, n)
  723.  
  724. {
  725.     cbuf(f, n, 11);
  726. }
  727.  
  728. cbuf12(f, n)
  729.  
  730. {
  731.     cbuf(f, n, 12);
  732. }
  733.  
  734. cbuf13(f, n)
  735.  
  736. {
  737.     cbuf(f, n, 13);
  738. }
  739.  
  740. cbuf14(f, n)
  741.  
  742. {
  743.     cbuf(f, n, 14);
  744. }
  745.  
  746. cbuf15(f, n)
  747.  
  748. {
  749.     cbuf(f, n, 15);
  750. }
  751.  
  752. cbuf16(f, n)
  753.  
  754. {
  755.     cbuf(f, n, 16);
  756. }
  757.  
  758. cbuf17(f, n)
  759.  
  760. {
  761.     cbuf(f, n, 17);
  762. }
  763.  
  764. cbuf18(f, n)
  765.  
  766. {
  767.     cbuf(f, n, 18);
  768. }
  769.  
  770. cbuf19(f, n)
  771.  
  772. {
  773.     cbuf(f, n, 19);
  774. }
  775.  
  776. cbuf20(f, n)
  777.  
  778. {
  779.     cbuf(f, n, 20);
  780. }
  781.  
  782. cbuf21(f, n)
  783.  
  784. {
  785.     cbuf(f, n, 21);
  786. }
  787.  
  788. cbuf22(f, n)
  789.  
  790. {
  791.     cbuf(f, n, 22);
  792. }
  793.  
  794. cbuf23(f, n)
  795.  
  796. {
  797.     cbuf(f, n, 23);
  798. }
  799.  
  800. cbuf24(f, n)
  801.  
  802. {
  803.     cbuf(f, n, 24);
  804. }
  805.  
  806. cbuf25(f, n)
  807.  
  808. {
  809.     cbuf(f, n, 25);
  810. }
  811.  
  812. cbuf26(f, n)
  813.  
  814. {
  815.     cbuf(f, n, 26);
  816. }
  817.  
  818. cbuf27(f, n)
  819.  
  820. {
  821.     cbuf(f, n, 27);
  822. }
  823.  
  824. cbuf28(f, n)
  825.  
  826. {
  827.     cbuf(f, n, 28);
  828. }
  829.  
  830. cbuf29(f, n)
  831.  
  832. {
  833.     cbuf(f, n, 29);
  834. }
  835.  
  836. cbuf30(f, n)
  837.  
  838. {
  839.     cbuf(f, n, 30);
  840. }
  841.  
  842. cbuf31(f, n)
  843.  
  844. {
  845.     cbuf(f, n, 31);
  846. }
  847.  
  848. cbuf32(f, n)
  849.  
  850. {
  851.     cbuf(f, n, 32);
  852. }
  853.  
  854. cbuf33(f, n)
  855.  
  856. {
  857.     cbuf(f, n, 33);
  858. }
  859.  
  860. cbuf34(f, n)
  861.  
  862. {
  863.     cbuf(f, n, 34);
  864. }
  865.  
  866. cbuf35(f, n)
  867.  
  868. {
  869.     cbuf(f, n, 35);
  870. }
  871.  
  872. cbuf36(f, n)
  873.  
  874. {
  875.     cbuf(f, n, 36);
  876. }
  877.  
  878. cbuf37(f, n)
  879.  
  880. {
  881.     cbuf(f, n, 37);
  882. }
  883.  
  884. cbuf38(f, n)
  885.  
  886. {
  887.     cbuf(f, n, 38);
  888. }
  889.  
  890. cbuf39(f, n)
  891.  
  892. {
  893.     cbuf(f, n, 39);
  894. }
  895.  
  896. cbuf40(f, n)
  897.  
  898. {
  899.     cbuf(f, n, 40);
  900. }
  901.  
  902.  
  903.